package basics;

import org.junit.Test;

/**
 * 测试装箱与拆箱和String常量池
 *
 * @author jiangwz
 * @create 2019/10/12.
 */
public class TestBoxingAndUnBoxing {


    @Test
    public void test02(){
        // 自动装箱方法 Integer.valueOf   拆箱方法 (Integer)a.intValue();
        Integer a = new Integer(3);
        Integer b = 3;                  // 将3自动装箱成Integer类型
        int c = 3;
        System.out.println(a == b);     // false 两个引用没有引用同一对象
        System.out.println(a == c);     // true a自动拆箱成int类型再和c比较
    }

    @Test
    public void testLong(){

        Long a = 127L;
        Long b = 127L;
        Long a1 = 128L;
        Long b1 = 128L;
        int a3 = 127;
        System.out.println(a == b);//true  因为Long有缓存, 在valueOf方法中 l >= -128 && l <= 127
        System.out.println(a1 == b1);// false 超出缓存要用equals方法比较
        System.out.println(a3 == a); //true   自动拆箱比较
    }

    @Test
    public void testValueOf(){
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        Long h = 2L;

        Integer a1 = 200;
        Integer b1 = 300;
        Integer c1 = 500;
        System.out.println(c1==(a1+b1)); //true 没懂 好像不在缓存之内 为什么相等 (我知道了 a1,b1先拆箱计算得到值, c1和值比较要拆箱,所以相等)
//         == 的作用：
//　　基本类型：比较的就是值是否相同
//　　引用类型：比较的就是地址值是否相同
//        equals 的作用:
//　　引用类型：默认情况下，比较的是地址值。
//        注：不过，我们可以根据情况自己重写该方法。一般重写都是自动生成，比较对象的成员变量值是否相同
        System.out.println(c==d);//true   Integer默认有缓存-128-127之间,用的是缓存,所以地址相等
        System.out.println(e==f);//false  超过范围,没有用缓存是不同的对象,地址不同
        System.out.println(c==(a+b));//true  a,b先拆箱(intValue),计算完后再装箱 地址还是相等
        System.out.println(c.equals(a+b));//true equals比较的是值,值确实相等
        System.out.println(g==(a+b));//true   Long和Integer的缓存一样-128-127之间
        System.out.println(g.equals(a+b)); //false 因为g是long型,a+b是int型,类型不同(类型相同才会比较),直接返回false,可以看源码
        System.out.println(g.equals(a+h));//true a是int型 h是long型 相加变为long型,再装箱,所以值相等
    }

    @Test
    public void case1(){
        Integer i1 = 40;
        Integer i2 = 40;
        Integer i3 = 0;
        Integer i4 = new Integer(40);
        Integer i5 = new Integer(40);
        Integer i6 = new Integer(0);
        System.out.println("i1=i2   " + (i1 == i2));//true  缓存所以相等
        System.out.println("i1=i2+i3   " + (i1 == i2 + i3));//true 拆箱所以相等
        System.out.println("i1=i4   " + (i1 == i4));//false // new Integer 不走valueOf方法所以不相等
        System.out.println("i4=i5   " + (i4 == i5));// false //new Integer 不走valueOf方法所以不相等
        // 这里要解释一下 因为Integer型的 i5+i6不能直接相加,
        // 必须拆箱 所以输出 i4==40, 又因为Integer不能和数值进行比较,所以 i4拆箱 40==40,返回true
        System.out.println("i4=i5+i6   " + (i4 == (i5 + i6)));// true  相加需要拆箱 拆箱后的值与 引用对象比较, 引用对象要拆箱 全部拆箱比较
        System.out.println("40=i5+i6   " + (40 == (i5 + i6)));// true 全部拆箱比较


    }

    @Test
    public void case2(){
        String str11 = "abcd";
        String str21 = new String("abcd");
        System.out.println(str11==str21);//false

        String str1 = "str";
        String str2 = "ing";
        String str3 = "str" + "ing";
        String str4 = str1 + str2;
        // 只有使用""号相加才会放入常量池中
        System.out.println(str3 == str4);//false

        String str5 = "string";
        System.out.println(str3 == str5);//true

        /**
         * String s = new String( "xyz" );
         * 在常量池中不存在xyz的时候,以下代码会创建2个对象
         * 1. 先去常量池中看看有没有xyz,有则返回,无则创建xyz放入常量池
         * 2. 看到new关键字后,会到堆内存中创建一个xyz的String型的对象
         */
        String s = new String( "xyz" );
    }
}
